﻿using System;
using System.Runtime.CompilerServices;

namespace BassTutor.Analysis
{
    /// <summary>
    /// Reverse bits in number
    /// </summary>
    public class Reverse
    {
        private static readonly int MAX = 16;
        private int[][] data=new int[MAX][];
        private bool[] computed = new bool[MAX];

        /// <summary>
        /// Reverse bits in number
        /// </summary>
        public Reverse()
        {
            for (int i = 0; i < MAX; ++i) computed[i] = false;
        }

        /// <summary>
        /// Return x with reversed bits 
        /// example: x = 9 bits = 6
        /// in binary system: 001001 -> 100100 )
        /// </summary>
        /// <param name="x">the number to be reversed</param>
        /// <param name="bits">the amount of bits should be considered</param>
        /// <returns></returns>
        public int this[int x,int bits] 
	    {
		    get {
                if (bits < 2 || bits >= MAX)
                    throw new IndexOutOfRangeException();
                if (x < 0 || x >= 1 << bits)
                    throw new IndexOutOfRangeException();
                if (!computed[bits])
                    compute(bits);
                return data[bits][x];
            }
	    }

        //it's not necesary antil i'll make paralel version of fft
        [MethodImpl(MethodImplOptions.Synchronized)]
        private void compute(int bits)
        {
            int N=1<<bits;
            data[bits] = new int[N];
            for (int i = 0; i < N; ++i)
                data[bits][i] = rev(i, bits);
            computed[bits] = true;
        }

        private int rev(int x, int bits)
        {
            int res = 0;
            for (int mask = 1 << bits - 1; mask > 0; mask >>= 1, x>>=1)
                if ((x & 1)!=0) 
                    res |= mask;
            return res;
        }
    }
}
